/*
 * Copyright (c) 2013.
 * 游戏服务器核心代码编写人陈磊拥有使用权
 * 联系方式：E-mail:13638363871@163.com ;qq:502959937
 * 个人博客主页：http://my.oschina.net/chenleijava
 */

package com.dc.gameserver.serverCore.service.cardModule;

import com.dc.gameserver.baseConfig.Config;
import com.dc.gameserver.exceptions.logicException;
import com.dc.gameserver.extComponents.utilsKit.util.random.Rnd;
import com.dc.gameserver.hardCode.PkStatus;
import com.dc.gameserver.hardCode.playerGameStatus;
import com.dc.gameserver.proto.gameserverprotoVo.*;
import com.dc.gameserver.serverCore.model.gamemodel.LevelModel;
import com.dc.gameserver.serverCore.model.gamemodel.script.ScriptFactory;
import com.dc.gameserver.serverCore.service.battle.BaseBattle;
import com.dc.gameserver.serverCore.service.battle.GameFormula;
import com.dc.gameserver.serverCore.service.battle.coreBattleLogic.ISingle;
import com.dc.gameserver.serverCore.service.character.GameCharacter;
import com.dc.gameserver.serverCore.service.character.Monster;
import com.dc.gameserver.serverCore.service.character.PlayerInstance;
import com.dc.gameserver.serverCore.service.managerService.ThreadPoolManager;
import com.google.protobuf.MessageLite;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.PooledByteBufAllocator;
import javolution.util.FastTable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author : 石头哥哥
 * Date: 13-10-26</br>
 * Time: 上午10:15</br>
 * Package: Server.ServerCore.Service.LicensingProcess</br>
 * 注解： 纸牌盒子对象   ，该对象产生的时机应该是在p1,p2匹配成功准备进入战斗；</br>
 *        销毁应该是玩家退出的时候</br>
 */
public class CardBox{

    private static final Logger LOGGER= LoggerFactory.getLogger(CardBox.class);

    /*** card box 编号*/
    private int cardBoxID;

    /**card 对象池**/
    private FastTable<Card> cardsPool=null;

    /**PK 中的游戏对象 CardBoxManager 对象 对应游戏pk列表  游戏对象****/
    private FastTable<GameCharacter> InGamePlayerList=null;
    /**临时出牌列表（判定玩家是否都出牌到预出牌临时区域）****/
    private FastTable<GameCharacter> checkOutCardPlayerList=null;
    /***出牌玩家列表*****/
    private FastTable<GameCharacter> tempOutCardPlayerList=null;
    /**回合计数***/
    private AtomicInteger roundCount=null;
    /**回合战斗对象**/
    private BaseBattle battle;


    /**
     *构造函数 ,cardBox资源不会被回收，由定时任务自动进行处理回收
     */
    public CardBox(int cardBoxID){
        this.cardBoxID= cardBoxID;
        this.InGamePlayerList=new FastTable<GameCharacter>();
        this.InGamePlayerList.clear();
        this.tempOutCardPlayerList=new FastTable<GameCharacter>();
        this.tempOutCardPlayerList.clear();
        this.checkOutCardPlayerList=new FastTable<GameCharacter>();
        this.checkOutCardPlayerList.clear();
        this.roundCount=new AtomicInteger(0);
        this.cardsPool=new FastTable<Card>();
        IntiCardPool();
    }





    /**
     * 销毁cardBox对象
     */
    public void destroyCardBox(){
        this.cardBoxID= -1;
        this.InGamePlayerList.clear();
        this.InGamePlayerList=null;
        this.tempOutCardPlayerList.clear();
        this.tempOutCardPlayerList=null;
        this.checkOutCardPlayerList.clear();
        this.checkOutCardPlayerList=null;
        this.cardsPool.clear();
        this.cardsPool=null;
        this.roundCount=null;
    }


    /**
     当前回合结束，清除当前回合中的资源，重置，准备下一次回合资源
     1秒=1 000毫秒
     System.currentTimeMillis() 毫秒级
     回合结束触发点
     */
    public void resetRoundResource(){
        //通知消息发送完毕   将会伤害以及动画播放
        notifyMessageSendOver();
        //已经构建好牌数据等待一段时间，推送下一回合的牌数据，通知玩家出牌
        registerRoundIntervalTaskAndExecutor(buildCardsBuffer(),this.InGamePlayerList);
    }

    /**
     *
     * 注册两个回合间隔（延迟执行下一个回合）任务并执行
     * @param cardBuffers   构建的数据 牌数据buffer
     * @param playerInstances
     */
    public void registerRoundIntervalTaskAndExecutor(final FastTable<ByteBuf> cardBuffers, final FastTable<GameCharacter> playerInstances){
        final Runnable task = new Runnable() {
            @Override
            public void run() {
                /**推送纸牌数据**/
                GameCharacter p1=playerInstances.get(0);
                GameCharacter p2=playerInstances.get(1);

                if ((p1 instanceof PlayerInstance)&&(p2 instanceof PlayerInstance)){
                    //将玩家的纸牌数据推送给玩家，怪物不推送数据
                    p1.DirectSend(cardBuffers.get(0));
                    p2.DirectSend(cardBuffers.get(1));
                    cardBuffers.clear();

                    /***syn card Num**/
                    p1.DirectSend(builderGameCharactorCardNum(p2));
                    p2.DirectSend(builderGameCharactorCardNum(p1));


                    /**syn information  magic  and  Shield  .在系统发牌之后，气血值和法力值将会被改变**/
                    ByteBuf inf1=buildBuf( p1);
                    ByteBuf inf2=buildBuf(p2);
                    for (GameCharacter player:playerInstances){
                        player.DirectSend(inf1.copy());
                    }
                    for (GameCharacter player:playerInstances){
                        player.DirectSend(inf2.copy());
                    }
                    inf1.release();inf1=null;
                    inf2.release();inf2=null;

                    /** notify player out cards*****/
//                    FastTable<GameCharacter> playerInstanceFastTable=new FastTable<GameCharacter>();
//                    int round=CardBoxManager.getCardBoxByID(cardBoxID).RoundCount();
//                    for (GameCharacter player:playerInstances){
//                        if (player.getDizzinessTimes()==0){           //可以出牌
//                            player.setActionOutCard(false);//设定出牌动作没有发生；如果在超时之前true，那么超时逻辑将不会被执行；
//                            playerInstanceFastTable.add(player);
//                            CardBoxManager.notifyOutCards(player, true,round);
//                        } else {
//                            player.setActionOutCard(true);  //默认当前状态出牌，否则会触发定时器执行导致问题
//                            CardBoxManager.notifyOutCards(player, false,round);//不可以可以出牌  ,当前状态处于眩晕
//                        }
//                    }
//
//                    /**
//                     * 进入回合出牌，开始计时，当没有玩家被通知出牌，那么
//                     * 回合计时器将不会生效，即进入回合计时逻辑，那么必定有玩家被通知出牌
//                     * 当回合逻辑计时到了之后，检查玩家是否出牌，如果没有出牌，那么就超时；
//                     */
//                    if (playerInstanceFastTable.size()>0){
//                        CardBoxManager.registerRoundOutCardTimeOutTaskAndExecutorForPVP(playerInstanceFastTable);
//                    } else {
//                        playerInstanceFastTable=null;
//                    }
                }else if ((p1 instanceof PlayerInstance)&&(p2 instanceof Monster)){
                    LOGGER.debug("PVE  ===============================================================111");
                    //PVE中 monster 使用神识成功，player 将会受到monster任何数据牌的攻击，自动进行一个回合
                    //
                    //PVE
                    //syn card  to player;
                    p1.DirectSend(cardBuffers.get(0));
                    cardBuffers.get(1).release();
                    cardBuffers.clear();

                    /***monster card num syn card Num to player **/
                    p1.DirectSend(builderGameCharactorCardNum(p2));

                    /**syn information  magic  and  Shield ,only send to player */
                    p1.DirectSend(buildBuf(p1));
                    p1.DirectSend(buildBuf(p2));

                    int round=CardBoxManager.getCardBoxByID(cardBoxID).RoundCount();
                    if (p1.getDizzinessTimes()==0){
                        CardBoxManager.notifyOutCards(p1, true,round);
                        CardBoxManager.registerRoundOutCardTimeOutTaskAndExecutorForPVE(p1);
                    }else {
                        CardBoxManager.notifyOutCards(p1,false,round);
                        registerRoundIntervalTaskAndExecutorOnly((Monster) p2,(PlayerInstance) p1);
                    }

                } else {
                    LOGGER.debug("PVE  ===============================================================222");
                    //PVE
                    //p1 monster , p2  PlayerInstance
                    p2.DirectSend(cardBuffers.get(1));
                    cardBuffers.get(0).release();
                    cardBuffers.clear();

                    /***monster card Num to player**/
                   p2.DirectSend(builderGameCharactorCardNum(p1));
                    /**syn information  magic  and  Shield ,only send to player */
                   p2.DirectSend(buildBuf(p2));
                   p2.DirectSend(buildBuf(p1));
                    int round=CardBoxManager.getCardBoxByID(cardBoxID).RoundCount();
                    if (p1 instanceof Monster&& p2 instanceof PlayerInstance){
                        if (p2.getDizzinessTimes()==0){
                            CardBoxManager.notifyOutCards(p2,true,round);
                            CardBoxManager.registerRoundOutCardTimeOutTaskAndExecutorForPVE(p2);
                        }else {
                            registerRoundIntervalTaskAndExecutorOnly((Monster)p1,(PlayerInstance)p2);
                        }
                    }
                }
            }
        };
        //注册两个回合间隔（延迟）定时任务 ,回合间隔不管在PVE PVP 都将会被执行  roundInterval时间后执行task
        ThreadPoolManager.getInstance().scheduleRoudIntervalTime(task,Config.DEFAULT_VALUE.GAME_VALUE.roundInterval);
        LOGGER.debug("当前回合数:"+this.roundCount.get()+"间隔 时间点：");
    }

    /**
     * 只有monster出牌
     * @param monster
     * @param player
     */
    private void  registerRoundIntervalTaskAndExecutorOnly(final Monster monster,final PlayerInstance player){
       final Runnable task=new Runnable() {
           @Override
           public void run() {
               /**
                *pve  p1处于眩晕状态中，玩家将不会出牌，
                *monster自动发起攻击,将计算结果推送给player；
                *自动进行一回合
                */
               FastTable<Card> monsterCard=monster.monsterOutCards();
               if (monsterCard!=null){
                   for (Card c:monsterCard){
                       monster.addOutCard(c);
                   }
                   monsterCard.clear();
                   monsterCard=null;  //purge list
                   int Dizziness=player.getDizzinessTimes();
                   if (Dizziness!=0){
                       Dizziness=Dizziness-1;
                       player.setDizzinessTimes(Dizziness);
                       if (Dizziness==0){
                           //notify  unDizzniess
                           dizzniessResponse.Builder builder= dizzniessResponse.newBuilder();
                           builder.setResult(playerGameStatus.undizziness.getStatus());
                           builder.setPlayerID(player.getID());
                           CardBoxManager.getCardBoxByID(player.getCardBoxID())
                                   .submitMessageToEveryOne(CardBox.wrappedBufferShort(dizzniessResponse.msgID.ID_VALUE, builder.build()));
                       }
                   }
                   //syn card   monsterCard--->p1
                   CardBoxManager.synCardList(monster,player);
                   //logic single out card; monster  out card
                   CardBoxManager.getCardBoxByID(monster.getCardBoxID()).getCheckOutCardPlayerList().clear();
                   ISingle.SINGLES[monster.getCardType().getType()].SingleLogicHandle(monster,player);
               }else {
                   //monster give out card;
                   int Dizziness=player.getDizzinessTimes();
                   if (Dizziness!=0){
                       Dizziness=Dizziness-1;
                       player.setDizzinessTimes(Dizziness);
                       if (Dizziness==0){
                           //notify  unDizzniess
                           dizzniessResponse.Builder builder= dizzniessResponse.newBuilder();
                           builder.setResult(playerGameStatus.undizziness.getStatus());
                           builder.setPlayerID(player.getID());
                           CardBoxManager.getCardBoxByID(player.getCardBoxID())
                                   .submitMessageToEveryOne(CardBox.wrappedBufferShort(dizzniessResponse.msgID.ID_VALUE, builder.build()));
                       }
                   }
                   flushBloodAndMagic();
                   resetRoundResource();
                   getTempOutCardPlayerList().clear();
               }

           }
       };
        //注册回合间隔定时任务
        ThreadPoolManager.getInstance().scheduleRoudIntervalTime(task,Config.DEFAULT_VALUE.GAME_VALUE.roundInterval);
    }


    /**
     * 初始化 card对象池
     * 注意牌类型概率来产生 ,点数则根据对象的属性来动态产生
     */
    private void IntiCardPool(){
       for (int i=0;i!=Config.DEFAULT_VALUE.GAME_VALUE.cardNum;++i){
           this.cardsPool.addLast(new Card());
       }
    }

    /**
     *将对象归还到对象池中
     * @param card
     */
    public void returnPool(Card card){
        if (card!=null){
            card.setCount(0); //牌点数
            card.setType(0);  //牌类型 1，2，3，4
            this.cardsPool.addLast(card);
        }else {
            throw new  logicException("card is null ,please check logic ");
        }
    }

    /**
     *
     * @param gameCharacter   游戏对象
     * @param cards  获取纸牌对象熟练
     * @return
     */
    public Card[] getRndCard(GameCharacter gameCharacter,int cards){
        LOGGER.debug("获取系统发牌数量:"+ cards+"当前玩家牌数量:"+gameCharacter.getCardlib().size()+"最大持牌数量:"+gameCharacter.getMaxHoldCard());
        Card[]cardArray=new Card[cards];
        for (int i=0;i!=cards;++i){
            int count= GameFormula.getCardCount(gameCharacter.getMinCount(),gameCharacter.getMaxCount()) ;  //点数
            int cardType=GameFormula.getCardType();
            Card card=this.cardsPool.pollFirst();//get first and remove it
            card.setCount(count);
            card.setType(cardType);
            cardArray[i]=card;
        }
        return cardArray;
    }

    /**
     * 补牌
     * 获取当前玩家回合完毕将被系统发的纸牌
     * 同时 恢复法力值=境界附加的恢复量+装备附加的恢复量+道具增加的恢复量
     * @param gameCharacter   获取纸牌对象的玩家
     * @return Card[]
     *
     *
     */
    public  Card[] getOutCardsAndRecoveryMagic(GameCharacter gameCharacter){
        Card[] cards=null;
        int maxCardsHold= gameCharacter.getMaxHoldCard();//最大持用牌数量
        int  currentCards=gameCharacter.getCurrentCardSize(); //当前对象持有的牌数量
        if (currentCards>maxCardsHold){
            throw  new IllegalArgumentException(currentCards+">>currentCards must be <= "+maxCardsHold+" please check logic.");
        }
        //recovery magic  ,被动恢复法力值
        int maxMagic=gameCharacter.getMaxMagic();
        int currentMagic=gameCharacter.getCurrentMagic();
        int temp=currentMagic+gameCharacter.getRecoveryMagic();
        if (temp>=maxMagic){
            gameCharacter.setCurrentMagic(maxMagic);
        }else {
            gameCharacter.setCurrentMagic(temp);
        }
        //当前牌数量等于maxCardsHold牌数量，撤销补牌  mission==0
        int mission=maxCardsHold-currentCards;
        if (mission==0)return cards;    //已经等于最大持牌数量
        int maxGetCardCard=gameCharacter.getMaxGetCard();//最大摸牌数

        if (mission>=maxGetCardCard){
            //最大补牌数maxOutCard
            cards=getRndCard(gameCharacter,maxGetCardCard);
            gameCharacter.add(cards);
            LOGGER.debug("获取牌的对象:"+gameCharacter+"获取后牌张数："+gameCharacter.getCardlib().size());
        }else {
            //最大补牌数mission;
            cards=getRndCard(gameCharacter,mission);
            gameCharacter.add(cards);
            LOGGER.debug("获取牌的对象:"+gameCharacter+"获取后牌张数："+gameCharacter.getCardlib().size());
        }
        return cards;
    }



    /**
     * 构建属性数据
     * @param gameCharacter
     * @return
     */

    private ByteBuf buildBuf(GameCharacter gameCharacter){
        //syn player information
        synResetRoundPlayerInfoResponse.Builder playerInfoVO=synResetRoundPlayerInfoResponse.newBuilder();
        playerInfoVO.setPlayerID(gameCharacter.getID());
        playerInfoVO.setMagic(gameCharacter.getCurrentMagic());
        playerInfoVO.setShield(gameCharacter.getCurrentShield());
        return CardBox.wrappedBufferShort(synResetRoundPlayerInfoResponse.msgID.ID_VALUE, playerInfoVO.build());
    }


    /**
     *构建gameCharacter牌数量
     * @param gameCharacter
     * @return
     */
    private ByteBuf builderGameCharactorCardNum (GameCharacter gameCharacter) {
        synPlayerCardNumResponse.Builder builder=synPlayerCardNumResponse.newBuilder();
        builder.setPlayerID(gameCharacter.getID());   //object ID
        builder.setCardNum(gameCharacter.getCardlib().size());  // obj  card num
        return CardBox.wrappedBufferShort(synPlayerCardNumResponse.msgID.ID_VALUE,builder.build());
    }


    /**
     *
     *  当前Thread线程构建 数据
     *  构建对象系统发牌 ，包装数据
     *  1.new  card;
     *  2.all  card;
     * @return
     */
    private   FastTable<ByteBuf> buildCardsBuffer(){
        FastTable<ByteBuf> byteBufFastTable=new FastTable<ByteBuf>();
        checkOutCardPlayerList.clear();
        for (GameCharacter gameCharacter:InGamePlayerList){  // first is p1,second is p2;
            gameCharacter.clearRoundResource();  //清空player资源  for next
            checkOutCardPlayerList.add(gameCharacter);//ready for next  check player out card
            //new card        system out card  to player or monster
              Card[] cards=this.getOutCardsAndRecoveryMagic(gameCharacter);
                synResetRoundCardResponse.Builder builder=synResetRoundCardResponse.newBuilder();
                if (cards!=null){
                    //new  card from system
                    for (com.dc.gameserver.serverCore.service.cardModule.Card card:cards){
                        netCardVO.Builder netCardBuilder=netCardVO.newBuilder();
                        netCardBuilder.setCardNum(card.getType());//编号
                        netCardBuilder.setCardCount(card.getCount());//点数
                        builder.addNewList(netCardBuilder.build()) ;
                    }
                }
                //all card
                FastTable<Card> PlayerCardList=gameCharacter.getCardlib();
                for (com.dc.gameserver.serverCore.service.cardModule.Card card:PlayerCardList){
                    netCardVO.Builder netCardBuilder=netCardVO.newBuilder();
                    netCardBuilder.setCardNum(card.getType());//编号
                    netCardBuilder.setCardCount(card.getCount());//点数
                    builder.addAllList(netCardBuilder.build());
                }
                builder.setPlayerID(gameCharacter.getID());
                /**同步系统发牌**/
                byteBufFastTable.add(CardBox.wrappedBufferShort(synResetRoundCardResponse.msgID.ID_VALUE, builder.build()));
        }
        return byteBufFastTable;
    }

    /**
     * 检查继续战斗准备状态是否ok
     * @return
     */
    public boolean checkKeepBattleReady(){
       boolean status=false;
       for (GameCharacter player:InGamePlayerList){
           if (player.getPkStatus()== PkStatus.NO_PK){
               return status;
           }
       }
       status=true;
       return status;
    }

    /**
     *
     * 技能，（攻击）使用是否成功 ,被技能（攻击）攻击气血伤害值
     */
    public void sendHurtRule(int playerID,int hurt,int skillID){
        hurtRuleResponse.Builder builder=  hurtRuleResponse.newBuilder();
        builder.setHurtShield(hurt);
        builder.setPlayerID(playerID);
        if (skillID!=0)builder.setSkillID(skillID);//技能编号
        submitMessageToEveryOne(wrappedBufferShort(hurtRuleResponse.msgID.ID_VALUE, builder.build()));
    }

    /**
     * 不向monster推送数据
     * 通知PK结果 战报
     * @param gameCharacter 战斗胜利对象
     *                      pve
     */
    public void notifyPkResult(final GameCharacter gameCharacter){
            //通知数据传输完毕
            notifyMessageSendOver();
            //判定玩家是否通关
            int roundTimes=roundCount.get();
            boolean battleStatus=false;
            levelOverResponse.Builder levelOverbuilder=levelOverResponse.newBuilder();
            GameCharacter  otherGameCharacter=getOtherPlayer(gameCharacter);
            if (gameCharacter instanceof PlayerInstance&&otherGameCharacter instanceof PlayerInstance){
                //PVP

            }else {
                //pve  notify player  battleStatus
                if (gameCharacter instanceof PlayerInstance){
                    battleStatus=true;
                }else{
                    battleStatus=false;
                }
                levelOverbuilder.setRoundTimes(roundTimes); //回合次数
                if (battleStatus){
                    PlayerInstance player=(PlayerInstance) gameCharacter;
                    //数据库 操作   关卡model
                    LevelModel levelModel=getBattle().getLevelModel(); //当前关卡model
                    int areaID=levelModel.getAreaID(); //当前关卡所属areaID
                    int levelType=levelModel.getLevelType();
                    if (levelType== 0x1){
                        FastTable<LevelModel> levelModelsList= ScriptFactory.mainLevelFastMap.get(areaID);
                        int lastLevelID=levelModelsList.getLast().getId();//最后一个关卡编号
                        //更新关卡信息
                        player.updateLevelAndArea(lastLevelID, levelModel, areaID, battleStatus,roundTimes);
                    }else  if (levelType== 0x2){ //神识关卡
                        player.updateSoulLevel(levelModel,battleStatus,roundTimes);
                    } else {       //隐藏关卡

                    }
                }else {
                    //战斗失败
                    levelOverbuilder.setBattleStatus(battleStatus); // true :闯关成功 false:闯关失败
                    submitMessageToEveryOne(wrappedBufferShort(levelOverResponse.msgID.ID_VALUE,levelOverbuilder.build()));
                }
            }

        //战斗奖励
        //int[0]:关卡编号；int[1]：掉落的物品类型编号;int[2]:掉落物品数量；int[3]：物品类型；
        if (gameCharacter instanceof PlayerInstance){
            int[] items=this.battle.invokeItem();
            //记录玩家获取关卡的物品信息
            if (items!=null){
                gameCharacter.insterItemToPlayer(items);
            }
        }
    }

    /*******************magic******************************************************/



    /**
     *  刷新玩家的气血和蓝
     *不向monster推送数据
     */
    public void flushBloodAndMagic(){
        for (GameCharacter gameCharacter:InGamePlayerList){
            gameCharacter.setBattleSkillID(0);//set skill id value of 0
            flushShieldAndMagicResponse.Builder builder=flushShieldAndMagicResponse.newBuilder();
            builder.setShield(gameCharacter.getCurrentShield());
            builder.setMagic(gameCharacter.getCurrentMagic());
            builder.setPlayerID(gameCharacter.getID())  ; //对象编号
            LOGGER.debug("GameCharacter:"+gameCharacter+">法力盾:"+ gameCharacter.getCurrentShield()+">法力值:"+gameCharacter.getCurrentMagic());
            submitMessageToEveryOne(wrappedBufferShort(flushShieldAndMagicResponse.msgID.ID_VALUE,builder.build()));
        }
    }

    /**
     * 获取当前的回合数
     * @return
     */
    public int RoundCount() {
        return roundCount.incrementAndGet();
    }

    /**
     *
     * 查找另一位玩家
     * @param gameCharacter
     * @return other  player
     */
    public GameCharacter getOtherPlayer(GameCharacter gameCharacter){
        GameCharacter otherPlayer=null;
        for (GameCharacter playerInstance:InGamePlayerList){
            if (!playerInstance.equals(gameCharacter)){
                otherPlayer=playerInstance;
                break;
            }
        }
        return otherPlayer;
    }


    /**
     *通知消息发送完毕
     *不向怪物推送消息
     */
    public void notifyMessageSendOver(){
        ByteBuf buf=wrappedBufferShort(sendMessangeOverResponse.msgID.ID_VALUE,null);
        for (GameCharacter player:InGamePlayerList){
            if (player instanceof PlayerInstance)player.DirectSend(buf.copy());
        }
        buf.release();
        buf=null;
    }

    /**
     *  初始化
     *  PVP , PVE
     *  玩家根据境界的不同，有最大手牌数，最大摸牌数，最大出牌数。
     *  回合战斗开始
     *  重置处于PK状态玩家纸牌
     *  注意CardBoxManager实例对象和 InGamePlayerList对应
     * @param p1 先手
     * @param p2 后手
     */
    public  void ClearAndIntiCardBox(GameCharacter p1,GameCharacter p2){
        p1.add(getRndCard(p1, p1.getMaxHoldCard()));
        p2.add(getRndCard(p2, p2.getMaxHoldCard()));
    }


    /**
     * 服务器不想monster推送消息
     * 提交消息给游戏中的每个玩家
     * 提交消息给游戏pk中的玩家
     * @param byteBuf
     */
    public void submitMessageToEveryOne(ByteBuf byteBuf){
        for (GameCharacter p:InGamePlayerList){
              p.DirectSend(byteBuf.copy());  //同步消息给玩家
        }
        byteBuf.release();
        byteBuf=null;
    }

    /**
     * 获取  cardBoxID
     * @return
     */
    public int getCardBoxID() {
        return cardBoxID;
    }

    /**
     *  获取出牌的玩家 列表 ---->已经出牌的玩家列表
     * @return
     */
    public FastTable<GameCharacter> getTempOutCardPlayerList() {
        return tempOutCardPlayerList;
    }


    /**
     *  每一个回合开始，作为判定玩家是否出牌，如果出牌，眩晕，放弃出牌，都将会被移除
     *  在没有个回合判定完毕之后将重新添加，
     * @return
     */
    public FastTable<GameCharacter> getCheckOutCardPlayerList() {
        return checkOutCardPlayerList;
    }
    /**
     *获取游戏中的PK对象 list
     * @return
     */
    public FastTable<GameCharacter> getInGamePlayerList() {
        return InGamePlayerList;
    }

    /**
     * 通过产生 获取平均随机值来打乱数组中元素的位置
     * Shuffle  array
     * @param array
     * @return  Object[]
     */
    private static Object[] Shuffle(Object[] array){
        int size=array.length;
        for (int i=size; i>1; i--)
            swap(array, i-1, Rnd.newInstance(Rnd.RandomType.UNSECURE_VOLATILE).directRandom().nextInt(i));
        return array;
    }

    /**
     * Swaps the two specified elements in the specified array.
     */
    private static void swap(Object[] arr, int i, int j) {
        Object tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }
    /**
     * Encoder buffer            </br>
     * 包长度2字节            </br>
     * @param ID  数据包编号
     * @param messageLite 将其转化为byte[]
     * @return
     */
    public static ByteBuf wrappedBufferShort(int ID, MessageLite messageLite) {
        ByteBuf buffer= PooledByteBufAllocator.DEFAULT.heapBuffer(0x40);
        buffer.setIndex(0,0x2);//设定writeIndex指针位置
        buffer.writeInt(ID); //编号
        if (messageLite!=null)buffer.writeBytes(messageLite.toByteArray());
        buffer.setShort(0,buffer.writerIndex()- 0x2);
        messageLite=null;
        return buffer;
    }
    public AtomicInteger getRoundCount() {
        return roundCount;
    }

    public BaseBattle getBattle() {
        return battle;
    }

    public void setBattle(BaseBattle battle) {
        this.battle = battle;
    }

}

